package tp.pr4.instructions;

import java.util.StringTokenizer;
import tp.pr4.NavigationModule;
import tp.pr4.RobotEngine;
import tp.pr4.instructions.exceptions.InstructionExecutionException;
import tp.pr4.instructions.exceptions.WrongInstructionFormatException;
import tp.pr4.items.ItemContainer;

/**
 * The Instruction for using an item. This Instruction works if the user writes 
 * OPERATE id or OPERAR id
 * @author Alvaro Saez Hernando
 * @author Noel Clemente Montero 
 */
public class OperateInstruction implements Instruction {

	private static final String LINE_SEPARATOR = System.lineSeparator();
	private String id;
	private NavigationModule navigation;
	private RobotEngine robot;
	private ItemContainer robotContainer;
	
	/**
	 * Default constructor.
	 */
	public OperateInstruction(){
		this.id = null;
		this.robotContainer = new ItemContainer();
		this.robot = null;
		this.navigation = null;
	}
	
	/**
	 * Creates a OperateInstruction using a ID 
	 * @param id
	 */
	public OperateInstruction(String id) {
		this.id = id;
		this.robotContainer = new ItemContainer();
		this.robot = null;
		this.navigation = null;
	}
	
	/**
	 * Parses the String returning an instance of OperateInstruction or throwing
	 * a WrongInstructionFormatException()
	 * @param cad text String to parse
	 * @return Instruction Reference to an instance of OperateInstruction
	 * @throws WrongInstructionFormatException When the String is not OPERATE|OPERAR <ID>
	 */
	public Instruction parse(String cad) throws WrongInstructionFormatException {
		
		StringTokenizer st = new StringTokenizer(cad, " ");
		String word = st.nextToken().toUpperCase();

		if ((word.equals("OPERATE")) || (word.equals("OPERAR"))) {
			if (st.hasMoreTokens()) {
				String id = st.nextToken();
				if (!st.hasMoreTokens())
					return new OperateInstruction(id);
				else
					throw new WrongInstructionFormatException("WALL·E says: I do not understand. Please repeat" + LINE_SEPARATOR);
			} 
			else
				throw new WrongInstructionFormatException("WALL·E says: I do not understand. Please repeat" + LINE_SEPARATOR);
		} 
		else
			throw new WrongInstructionFormatException("WALL·E says: I do not understand. Please repeat" + LINE_SEPARATOR);
	}

	/**
	 * Returns a description of the Instruction syntax. The string does not end with the line separator. It is up to the caller adding it before printing.
	 * @return the Instruction syntax OPERATE|OPERAR <ID>
	 */
	public String getHelp() {
		return "OPERATE|OPERAR <id>" + LINE_SEPARATOR;
	}

	/**
	 * Set the execution context. The method receives the entire engine (engine, 
	 * navigation and the robot container) even though the actual implementation 
	 * of execute() may not require it.
	 * @param engine The robot engine
	 * @param navigation The information about the game, i.e., the places, current 
	 * direction and current heading to navigate
	 * @param robotContainer The inventory of the robot
	 */
	public void configureContext(RobotEngine engine,NavigationModule navigation, ItemContainer robotContainer) {
		this.navigation = navigation;
		this.robot = engine;
		this.robotContainer = robotContainer;
	}

	/**
	 * The robot uses the requested item.
	 * @throws InstructionExecutionException When the robot inventory does not contain 
	 * an item with this name or when the item cannot be used
	 */
	public void execute() throws InstructionExecutionException {
		
		if(robotContainer.containsItem(this.id)){ // si el item existe.
			if(robotContainer.getItem(this.id).canBeUsed()){ //mira el ID del objeto y si se puede usar
				if (robotContainer.getItem(this.id).use(this.robot, this.navigation)){ // coge el item y lo usa y devuelve true si se ha usao
					if (!robotContainer.getItem(this.id).canBeUsed()){ //comprueba si el objeto puede volve ra ser usado
						robotContainer.pickItem(this.id);
						System.out.println("WALL·E says: What a pity! I have no more " + this.id + " in my inventory");
					}
				}
			else throw new InstructionExecutionException("WALL·E says: I have problems using the object " + this.id);	
			}//end if getItem	
		}
		else throw new InstructionExecutionException("WALL·E says: I have not such object");
	}
		

}
